﻿/*
 * Copyright 2023 KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <QDebug>

#include "powertray.h"
#include "powerwindow.h"
#include "kwindowsystem.h"

#define UPM_SETTINGS_SCHEMA		           "org.ukui.power-manager"
#define UPM_SETTINGS_DISPLAY_LEFT_TIME     "dispaly-left-time-of-charge-and-discharge"

PowerTray::PowerTray(QObject *parent) : QObject(parent)
{
    m_powerSupplyDev = new PowerSupplyDev(this);

    qDebug() << "upower version is:" << m_powerSupplyDev->getUpowerDaemonVersion();

    if (0 == m_powerSupplyDev->getBatteryNum()) {
        exit(0);
    }

    initPowerTray();

    m_criticalPercentageAction = new CriticalPercentageAction(m_powerSupplyDev, this);
}

PowerTray::~PowerTray()
{
    if (nullptr != m_TrayMenu) {
        delete m_TrayMenu;
        m_TrayMenu = nullptr;
    }

    if (nullptr != m_powerWindow) {
        delete m_powerWindow;
        m_powerWindow = nullptr;
    }
}

void PowerTray::initPowerTray()
{
    m_settings = new QGSettings(UPM_SETTINGS_SCHEMA);
    m_showBatteryLeftTime = m_settings->get(UPM_SETTINGS_DISPLAY_LEFT_TIME).toInt();

    m_acChangeTimer = new QTimer(this);
    m_isPowerSupplyChange = false;
    connect(m_acChangeTimer, &QTimer::timeout, this, [=](){
        m_isPowerSupplyChange = false;
        m_acChangeTimer->stop();
    });

    updateBatteryInfo();

    m_trayIcon = new QSystemTrayIcon(this);
    setTrayIconToolTipForAcOnlineChanged(m_acOnlineState, m_batteryPercentage);
    m_trayIconName = m_powerSupplyDev->getBatteryIconName();
    setTrayIcon(m_trayIconName);

    initTrayMenuUI();
    initPowerWindowUI();

    connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
            this, SLOT(onActivatedIcon(QSystemTrayIcon::ActivationReason)));

    connect(m_powerSupplyDev, &PowerSupplyDev::acOnlineStateChanged,
            this, &PowerTray::dealAcOnlineStateChanged);
    connect(m_powerSupplyDev, &PowerSupplyDev::batteryInfoChanged,
            this, &PowerTray::dealBatteryInfoChanged);
}

void PowerTray::initTrayMenuUI()
{
    qDebug() << "init tray menu ui";
    m_TrayMenu = new QMenu();
    m_TrayMenu->setAttribute(Qt::WA_TranslucentBackground);
    m_trayIcon->setContextMenu(m_TrayMenu);
    QAction *setPreference = new QAction(m_TrayMenu);
    QIcon icon = QIcon::fromTheme("document-page-setup-symbolic");
    setPreference->setIcon(icon);
    setPreference->setText(tr("SetPower"));
    connect(setPreference, &QAction::triggered,[=]{QProcess::startDetached(QString("ukui-control-center -m Power"));});
    m_TrayMenu->addAction(setPreference);
}

void PowerTray::initPowerWindowUI()
{
    qDebug() << "init power window ui";
    m_powerWindow = new powerwindow();
    m_powerWindow->hide();

    setPowerWindowProperties();
    m_powerWindow->setPowerStateLabelForAcOnlineChanged();
}

void PowerTray::setPowerWindowProperties()
{
    m_powerWindow->setIconName(m_trayIconName);
    m_powerWindow->setAcOnlineState(m_acOnlineState);
    m_powerWindow->setBatteryState(m_batteryState);
    m_powerWindow->setBatteryPercentage(m_batteryPercentage);
    m_powerWindow->setShowPowerLeftTime(m_showBatteryLeftTime);
    m_powerWindow->setBatteryLeftTime(
                m_powerSupplyDev->getTimeToFull(),
                m_powerSupplyDev->getTimeToEmpty());
}

void PowerTray::setTrayIconToolTipForAcOnlineChanged(bool acOnlineState, double percentage)
{
    if (true == acOnlineState) {
        if (100 == percentage) {
            m_trayIcon->setToolTip(tr("fully charged (100%)"));
        } else {
            m_trayIcon->setToolTip(tr("%1% available (plugged in)").arg(percentage));
        }
    } else {
        m_trayIcon->setToolTip(tr("%1% remaining").arg(percentage));
    }
}

void PowerTray::setTrayIconToolTipForBatteryInfoChanged(double percentage)
{
    qlonglong batteryLeftTime = 0;
    int hour = 0;

    switch (m_powerSupplyDev->getBatteryState()) {
        case battery_state_unknown:
        case battery_state_fully:
            if (100 == percentage) {
                m_trayIcon->setToolTip(tr("fully charged (100%)"));
            } else {
                m_trayIcon->setToolTip(tr("%1% remaining").arg(percentage));
            }
            break;

        case battery_state_charging:
            batteryLeftTime = m_powerSupplyDev->getTimeToFull();
            if (0 == m_showBatteryLeftTime || 0 == batteryLeftTime || percentage > 95 ) {
                if (100 == percentage) {
                    m_trayIcon->setToolTip(tr("fully charged (100%)"));
                } else {
                    m_trayIcon->setToolTip(tr("%1% available (plugged in)").arg(percentage));
                }
            } else {
                hour = batteryLeftTime / 3600;
                if (0 == hour) {
                    m_trayIcon->setToolTip(tr("%1 min to fully charge (%2%)")
                                           .arg(((batteryLeftTime) % 3600) / 60)
                                           .arg(percentage));
                } else if (hour > 10) {
                    m_trayIcon->setToolTip(tr("%1% available (plugged in)").arg(percentage));
                } else {
                    m_trayIcon->setToolTip(tr("%1 hr %2 min to fully charge (%3%)")
                                           .arg(hour)
                                           .arg(((batteryLeftTime) % 3600) / 60)
                                           .arg(percentage));
                }
            }
            break;

        case battery_state_discharging:
            batteryLeftTime = m_powerSupplyDev->getTimeToEmpty();
            if (0 == m_showBatteryLeftTime || 0 == batteryLeftTime) {
                m_trayIcon->setToolTip(tr("%1% remaining").arg(percentage));
            } else {
                hour = batteryLeftTime / 3600;
                if (0 == hour) {
                    m_trayIcon->setToolTip(tr("%1 min (%2%) remaining")
                                           .arg(((batteryLeftTime) % 3600) / 60)
                                           .arg(percentage));
                } else if (hour > 20) {
                    m_trayIcon->setToolTip(tr("%1% remaining").arg(percentage));
                } else {
                    m_trayIcon->setToolTip(tr("%1 hr %2 min (%3%) remaining")
                                           .arg(hour)
                                           .arg(((batteryLeftTime) % 3600) / 60)
                                           .arg(percentage));
                }
            }
            break;

        default:
            m_trayIcon->setToolTip(tr("%1% remaining").arg(percentage));
            break;
    }
}

void PowerTray::setTrayIcon(QString strIconName)
{
    qDebug() << "icon name is : " << strIconName;
    if (!strIconName.isNull()) {
        QIcon icon = QIcon::fromTheme(strIconName);
        m_trayIcon->setIcon(icon);
        m_trayIcon->show();
    } else {
        m_trayIcon->hide();
    }
}

void PowerTray::onActivatedIcon(QSystemTrayIcon::ActivationReason reason)
{
    if (reason == 3) {
        bool isVisible = m_powerWindow->isVisible();
        if (true == isVisible) {
            qDebug() << "m_powerWindow isVisible:" << isVisible;
            m_powerWindow->hide();
        } else {
            qDebug() << "m_powerWindow isVisible:" << isVisible;
            m_powerWindow->showPowerWindow();
        }
    } else {
        qDebug() << "on Activated Icon reason:" << reason;
    }
}

void PowerTray::acOnlineStateChangedAction()
{
    updateBatteryInfo();

    //deal tray icon
    setTrayIconToolTipForAcOnlineChanged(m_acOnlineState, m_batteryPercentage);
    m_trayIconName = m_powerSupplyDev->getBatteryIconName();
    setTrayIcon(m_trayIconName);

    //deal power window
    setPowerWindowProperties();
    m_powerWindow->setPowerStateLabelForAcOnlineChanged();
}

void PowerTray::dealAcOnlineStateChanged(int index, bool value)
{
    qDebug() << "power tray ac online state changed";
    m_isPowerSupplyChange = true;
    m_acChangeTimer->start(60 * 1000);

    acOnlineStateChangedAction();
}

void PowerTray::dealBatteryInfoChanged(int index, QStringList batteryInfoChangedList)
{
    qDebug() << "power tray battery info changed";
    if (true == m_isPowerSupplyChange) {
        qDebug() << "ac online changed, not deal battery info changed";
        acOnlineStateChangedAction();
        return ;
    }

    m_showBatteryLeftTime = m_settings->get(UPM_SETTINGS_DISPLAY_LEFT_TIME).toInt();

    updateBatteryInfo();

    //deal tray icon
    setTrayIconToolTipForBatteryInfoChanged(m_batteryPercentage);

    QString trayIconName = m_powerSupplyDev->getBatteryIconName();
    if (m_trayIconName != trayIconName) {
        m_trayIconName = trayIconName;
        setTrayIcon(m_trayIconName);
    }

    //deal power window
    setPowerWindowProperties();
    m_powerWindow->setPowerStateLabelForBatteryInfoChanged();
}

void PowerTray::updateBatteryInfo()
{
    m_acOnlineState = m_powerSupplyDev->getAcOnlineState();
    qDebug() << "power tray ac online:" << m_acOnlineState;
    m_batteryState = m_powerSupplyDev->getBatteryState();
    qDebug() << "power tray battery state:" << m_batteryState;
    m_batteryPercentage = m_powerSupplyDev->getBatteryPercentage();
    qDebug() << "power tray battery percentage:" << m_batteryPercentage;
}

